<template>
  <div class="ml-container">
    <div ref="sceneBox" id="scene-box"></div>
  </div>
</template>
<script setup lang="ts">
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { ref, onMounted, onUnmounted } from 'vue'
const sceneBox = ref(null)
const width = innerWidth
const height = innerHeight
let scene = new THREE.Scene()
scene.background = new THREE.Color('#fff')
let camera = new THREE.PerspectiveCamera(65, width / height, 0.1, 1000)
camera.position.set(0, 100, 100)
camera.lookAt(0, 0, 0)
let renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(width, height)
const gltfLoader = new GLTFLoader()
const texLoader = new THREE.TextureLoader()
const axesHelper = new THREE.AxesHelper(150)
// scene.add(axesHelper)
const controls = new OrbitControls(camera, renderer.domElement)
controls.addEventListener('change', () => {
  renderer.render(scene, camera)
})
// 初始化3D场景
const init3D = () => {
  sceneBox.value.appendChild(renderer.domElement)
  loadGround()
  loadModel()
  loadLight()
  loadSkyBox()
}
// 加载地面
const loadGround = () => {
  const mainPlane = new THREE.PlaneGeometry(width, height)
  const texture = texLoader.load('/texture/sndm.jpg')
  const cement = new THREE.MeshLambertMaterial({
    map: texture,
    side: THREE.DoubleSide
  })
  const cementGround = new THREE.Mesh(mainPlane, cement)
  cementGround.rotateX(Math.PI / 2)
  scene.add(cementGround)
  renderer.render(scene, camera)
}
// 加载建筑模型
const loadModel = () => {
  gltfLoader.load('/models/xzbuild.gltf', (gltf) => {
    scene.add(gltf.scene)
    renderer.render(scene, camera)
  })
  gltfLoader.load('/models/ssbuild.gltf', (gltf) => {
    gltf.scene.scale.set(1.3, 1.3, 1.3)
    gltf.scene.rotateY(-Math.PI / 2)
    gltf.scene.position.set(28, 0, -40)
    scene.add(gltf.scene)
    renderer.render(scene, camera)
  })
  gltfLoader.load('/models/ckbuild.gltf', (gltf) => {
    gltf.scene.scale.set(1.2, 1.2, 1.2)
    // gltf.scene.rotateY(-Math.PI / 2)
    gltf.scene.position.set(-6, 0, -70)
    scene.add(gltf.scene)
    renderer.render(scene, camera)
  })
}
// 加载光照
const loadLight = () => {
  const ambient = new THREE.AmbientLight('#fff', 0.5)
  scene.add(ambient)
  const sunLight = new THREE.DirectionalLight(0xffffff, 1)
  sunLight.position.set(100, 100, 100)
  sunLight.castShadow = true
  scene.add(sunLight)
  renderer.render(scene, camera)
}
// 加载天空盒
const loadSkyBox = () => {
  const cubeTexture = new THREE.CubeTextureLoader().setPath('/texture/').load([
    'posx.jpg',
    'negx.jpg', //左右
    'posy.jpg',
    'negy.jpg', //上下
    'posz.jpg',
    'negz.jpg' //前后
  ])
  // 添加背景纹理
  scene.background = cubeTexture
}
const destroyThreejs = () => {
  try {
    renderer.dispose()
    renderer.forceContextLoss()
    renderer.content = null
    let gl = renderer.domElement.getContext('webgl')
    if (gl && gl.getExtension('WEBGL_lose_context')) {
      gl.getExtension('WEBGL_lose_context').loseContext()
    }
    renderer = null
    camera = null
    scene.traverse((child) => {
      if (child.material) {
        child.material.dispose()
      }
      if (child.geometry) {
        child.geometry.dispose()
      }
      child = null
    })
    scene = null
  } catch (e) {
    console.error('Failed to destroy threejs', e)
  }
}
onMounted(() => {
  init3D()
})
onUnmounted(() => {
  destroyThreejs()
})
</script>
<style scoped lang="scss">
.ml-container {
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 1;
  color: #f00;
  font-size: vh(40);
}
#scene-box {
  width: 100%;
  height: 100%;
}
</style>
